﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Boomerang.Common.Configuration;
using System.Collections.ObjectModel;
using System.Diagnostics;

namespace Boomerang.Service.Threading
{
    public class ThreadManager
    {
        static ManualResetEvent[] doneEvents;

        public static void DoWork()
        {
            Trace.TraceInformation("Retrieving Organizations");
            ReadOnlyCollection<Organization> orgs;

            try
            {

                orgs = ConfigurationManager.GetActiveOrganizations();
            }
            catch (Exception ex)
            {
                Trace.TraceError("Failed to load organizations. {0} \n {1}", ex.Message, ex.StackTrace);
                return;
            }

            Trace.TraceInformation("Number of Organizations found {0}", orgs.Count);

            doneEvents = new ManualResetEvent[orgs.Count * 2];

            for (int index = 0; index < orgs.Count; index++)
            {
                Trace.TraceInformation("Preparing Sending and Receiving Threads {0} ¦ Organization {1}", index, orgs[index]);
                try
                {                    
                    doneEvents[index] = new ManualResetEvent(false);
                    ThreadPool.QueueUserWorkItem(new WorkerThreadSend(orgs[index], doneEvents[index], index).ThreadPoolCallback);
                    Trace.TraceInformation("Sending Thread {0} queued ", index);

                }
                catch (Exception ex)
                {
                    Trace.TraceError("Failed to initialize Sending Thread for Organization {0}. {1} \n {2}", orgs[index], ex.Message, ex.StackTrace);
                    if (doneEvents[index] != null) doneEvents[index].Set();
                }

                try
                {
                    doneEvents[index + orgs.Count] = new ManualResetEvent(false);
                    ThreadPool.QueueUserWorkItem(new WorkerThreadReceive(orgs[index], doneEvents[index + orgs.Count], index).ThreadPoolCallback);
                    Trace.TraceInformation("Receiving Thread {0} queued ", index);
                }
                catch (Exception ex)
                {
                    Trace.TraceError("Failed to initialize Receiving Thread for Organization {0}. {1} \n {2}", orgs[index], ex.Message, ex.StackTrace);
                    if (doneEvents[index + orgs.Count] != null) doneEvents[index + orgs.Count].Set();
                }
            }

            Trace.TraceInformation("Entering on wait for thread workers completition. Number of workers {0} ", doneEvents.Length);
            if (orgs.Count>0) WaitHandle.WaitAll(doneEvents);
            Trace.TraceInformation("Exiting wait for thread workers completition. Number of workers completed {0} ", doneEvents.Length);

        }

    }
}
